package com.wzdigit.wms.wms.service.mid;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wzdigit.mes.basic.api.BasicDataItemDetailApi;
import com.wzdigit.mes.basic.api.BasicGetCustomerApi;
import com.wzdigit.mes.basic.api.BasicSimpleCodeRuleApi;
import com.wzdigit.mes.basic.dto.CustomerDto;
import com.wzdigit.mes.basic.dto.DataItemDetailDTO;
import com.wzdigit.wms.basic.domain.asn.AsnDtl;
import com.wzdigit.wms.basic.domain.asn.AsnHeader;
import com.wzdigit.wms.basic.domain.basic.Sku;
import com.wzdigit.wms.basic.domain.basic.Warehouse;
import com.wzdigit.wms.basic.domain.inventory.Lotno;
import com.wzdigit.wms.basic.domain.mapping.CodeMapping;
import com.wzdigit.wms.basic.domain.mid.IfTransferDtl;
import com.wzdigit.wms.basic.domain.mid.IfTransferHeader;
import com.wzdigit.wms.basic.domain.mid.JobSyncErrorData;
import com.wzdigit.wms.basic.domain.mid.dtos.IfTransferHeaderDto;
import com.wzdigit.wms.basic.domain.transfer.GdnDtl;
import com.wzdigit.wms.basic.domain.transfer.GdnHeader;
import com.wzdigit.wms.basic.domain.transfer.TransferDtl;
import com.wzdigit.wms.basic.domain.transfer.TransferHeader;
import com.wzdigit.wms.basic.enums.*;
import com.wzdigit.wms.basic.mapper.core.basic.SkuMapper;
import com.wzdigit.wms.basic.mapper.core.basic.WarehouseMapper;
import com.wzdigit.wms.basic.mapper.core.mid.IfTransferDtlMapper;
import com.wzdigit.wms.basic.mapper.core.mid.IfTransferHeaderMapper;
import com.wzdigit.wms.basic.mapper.core.mid.JobSyncErrorDataMapper;
import com.wzdigit.wms.basic.mapper.core.order.AsnDtlMapper;
import com.wzdigit.wms.basic.mapper.core.order.AsnHeaderMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnDtlMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.GdnHeaderMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.TransferDtlMapper;
import com.wzdigit.wms.basic.mapper.core.transfer.TransferHeaderMapper;
import com.wzdigit.wms.wms.constant.SyncTypeConstant;
import com.wzdigit.wms.wms.exception.SyncException;
import com.wzdigit.wms.basic.service.code.LotnoService;
import com.wzdigit.wms.wms.service.mapping.CodeMappingNewService;
import lombok.extern.slf4j.Slf4j;
import net.dreamlu.mica.core.utils.BeanUtil;
import net.dreamlu.mica.core.utils.CollectionUtil;
import org.apache.dubbo.config.annotation.Reference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * <p>
 * 接口中间表-调拨单表头 服务实现类
 * </p>
 *
 * @author
 * @since 2021-03-17
 */
@Service
@Slf4j
public class IfTransferHeaderService {

    @Autowired
    private IfTransferHeaderMapper ifTransferHeaderMapper;

    @Autowired
    private IfTransferDtlMapper ifTransferDtlMapper;

    @Autowired
    private GdnHeaderMapper gdnHeaderMapper;

    @Autowired
    private GdnDtlMapper gdnDtlMapper;

    @Autowired
    private AsnHeaderMapper asnHeaderMapper;

    @Autowired
    private AsnDtlMapper asnDtlMapper;

    @Autowired
    private SkuMapper skuMapper;

    @Autowired
    private JobSyncErrorDataMapper jobSyncErrorDataMapper;

    @Autowired
    private TransferHeaderMapper transferHeaderMapper;

    @Autowired
    private TransferDtlMapper transferDtlMapper;

    @Autowired
    private SyncErrorDataService syncErrorDataService;

    @Autowired
    private LotnoService lotnoService;

    @Autowired
    private WarehouseMapper warehouseMapper;

    @Autowired
    private CodeMappingNewService codeMappingNewService;

    @Reference(version = "${dubbo.providers.basic.customer.api.version:1.0.0}", check = false, timeout = 300000)
    private BasicGetCustomerApi basicGetCustomerApi;

    @Reference(version = "${dubbo.consumers.basic.data.item.detail.api:1.0.0}", check = false, timeout = 300000)
    private BasicDataItemDetailApi dataItemDetailApi;

    @Reference(version = "${dubbo.consumers.basic.simple.code.rule.api:1.0.0}", check = false)
    BasicSimpleCodeRuleApi basicSimpleCodeRuleApi;

    @Value(value = "${default_owner.code}")
    private String DEFAULT_OWNER;

    @Value(value = "${default_owner.name}")
    private String DEFAULT_OWNER_NAME;

    private final String DATA_NAME = "退货待修品仓";

    private final String DATA_CODE = "THDXP";

    @Value("${order_code.gdn.code}")
    private String gdnNoRule;

    private final String R99 = "ASN_R99"; //生成编码的规则
    private final String R08 = "ASN_R08";

    private final String D99 = "GDN_D99";
    private final String D08 = "GDN_D08";

    private final String T03 = "TRANSFER_T03";
    private final String T04 = "TRANSFER_T04";
    private final String T05 = "TRANSFER_T05";
    private final String T06 = "TRANSFER_T06";

    private String syncType = SyncTypeConstant.IF_TRANSFER; //默认调拨
    private String billCodeRule = "";
    private String billTypeGloble = ""; //全局类型。写进表里的类型

    public List<IfTransferHeaderDto> selectSyncData() {
        ArrayList<IfTransferHeaderDto> ifTransferHeaderDtos = new ArrayList<>();
        List<IfTransferHeader> selectSyncData = ifTransferHeaderMapper.selectList(new QueryWrapper<>(new IfTransferHeader().setAttribute10("0")));
        //List<IfTransferHeader> selectSyncData = ifTransferHeaderMapper.selectList(new QueryWrapper<>(new IfTransferHeader().setAttribute10("0").setBillNo("MV2111120066")));
        if (!CollectionUtil.isEmpty(selectSyncData)) {
            for (IfTransferHeader ifTransferHeader : selectSyncData) {
                IfTransferHeaderDto ifTransferHeaderDto = new IfTransferHeaderDto();
                BeanUtil.copyNonNull(ifTransferHeader, ifTransferHeaderDto);
                List<IfTransferDtl> ifTransferDtls = ifTransferDtlMapper.selectList(new QueryWrapper<>(new IfTransferDtl().setIfTransferHeaderId(ifTransferHeader.getIfTransferHeaderId())));
                ifTransferHeaderDto.setIfTransferDtlList(ifTransferDtls);
                ifTransferHeaderDtos.add(ifTransferHeaderDto);
            }
        }
        return ifTransferHeaderDtos;
    }

    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public synchronized void syncData(IfTransferHeaderDto data, boolean isSyncError) throws Exception {
        String billNo = data.getBillNo();
        String billType = data.getBillType();
        if (billType == null) {
            throw new SyncException(syncType, billNo, "单据类型为空");
        }
        this.changeType(billType);
        //选择同步类型
        if (billType.equals("1") || billType.equals("2") || billType.equals("7") || billType.equals("8")) {
            //一、调拨业务：1借机-T05、2还机-T06、7组织间调拨-T03、8销售订单调拨-T04
            syncType = SyncTypeConstant.IF_TRANSFER;
            this.syncIfTransfer(data, isSyncError, syncType);
        } else if (billType.equals("4") || billType.equals("5")) {
            //二、入库业务：4其他入库-R99、5零部件入库-R08
            syncType = SyncTypeConstant.IF_TRANSFER_IN;
            this.syncIfTransferIn(data, isSyncError, syncType);
        } else if (billType.equals("3") || billType.equals("6")) {
            //三、出库业务：3其他出库-D99、6零部件出库-D08
            syncType = SyncTypeConstant.IF_TRANSFER_OUT;
            this.syncIfTransferOut(data, isSyncError, syncType);
        } else {
            throw new SyncException(syncType, billNo, "无效的单据类型");
        }
    }


    /**
     * 调拨出库 发货单
     *
     * @param data
     * @param isSyncError
     * @param syncType
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void syncIfTransferOut(IfTransferHeaderDto data, boolean isSyncError, String syncType) throws Exception {
        String billNo = data.getBillNo();
        List<IfTransferDtl> ifTransferDtlList = data.getIfTransferDtlList();
        //调拨出库 同步到 发货单 GDN
        if (CollectionUtil.isEmpty(ifTransferDtlList)) {
            throw new SyncException(syncType, billNo, "该调拨入库单下没有明细");
        }
        IfTransferDtl ifTransferDtl1 = ifTransferDtlList.get(0);
        GdnHeader gdnHeader = new GdnHeader();
        //发货单号系统生成
        //生成发货单号
        String gdnNo = null;
        try {
            gdnNo = this.generateCode(data.getBillType());
        } catch (Exception e) {
            e.printStackTrace();
            throw new SyncException(syncType, billNo, "生成发货单号失败");
        }
        if (gdnNo == null) {
            throw new SyncException(syncType, billNo, "生成发货单号失败");
        }
        gdnHeader.setGdnNo(gdnNo);
        gdnHeader.setSourceShipNotice(billNo);
        gdnHeader.setFactory(ifTransferDtl1.getFromOrg());
        gdnHeader.setGdnType(billTypeGloble);
        gdnHeader.setStatus(GdnHeaderStatusEnum.CREATE.code);
        gdnHeader.setGdnCreateTime(data.getCreateTime());
        gdnHeader.setGdnCreateUser(data.getCreateUser());
        gdnHeader.setComments(data.getRemarks());
        DataItemDetailDTO dataItem = dataItemDetailApi.getDataItemDetailByPCodeAndName(DEFAULT_OWNER, DEFAULT_OWNER_NAME);
        gdnHeader.setOwner(dataItem == null || dataItem.getItemValue() == null ? 0 : Integer.parseInt(dataItem.getItemValue()));
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            gdnHeader.setShipDate(dateFormat.parse(data.getAttribute1())); //出库日期（其他出库）
        } catch (ParseException e) {
            throw new SyncException(syncType, billNo, "出库日期时间格式有误");
        }
        CustomerDto customer = basicGetCustomerApi.getCustomerByCode(data.getAttribute2());
//        if (customer == null || customer.getCustomerId() == null) {
//            throw new SyncException(syncType, billNo, "客户" + data.getAttribute2() + "不存在");
//        }
        if (customer != null) {
            gdnHeader.setCustomer(customer.getCustomerId());
        }
        gdnHeader.setCtnrShipNo(data.getAttribute3()); //装柜发货单号（其他出库）
        GdnHeader headerRecord = gdnHeaderMapper.selectOne(new QueryWrapper<>(new GdnHeader().setRefCntrNo(gdnHeader.getRefCntrNo()).setSourceShipNotice(billNo)));
        if (headerRecord == null) {
            gdnHeader.setCreateTime(new Date());
            gdnHeader.setCreateUser("system");
            gdnHeaderMapper.insert(gdnHeader);
        } else {
            gdnHeader.setGdnHeaderId(headerRecord.getGdnHeaderId());
            gdnHeader.setGdnNo(headerRecord.getGdnNo());
            gdnHeader.setModifyTime(new Date());
            gdnHeader.setModifyUser("system");
            gdnHeaderMapper.updateById(gdnHeader);
        }
        int i = 1;
        for (IfTransferDtl ifTransferDtl : ifTransferDtlList) {
            boolean isUpdate = true;
            GdnDtl gdnDtlRecord = gdnDtlMapper.selectOne(new QueryWrapper<>(new GdnDtl().setSourceShipNoticeItem(ifTransferDtl.getBillLineNo()).setGdnHeaderId(gdnHeader.getGdnHeaderId())));
            if (gdnDtlRecord == null) {
                isUpdate = false;
                gdnDtlRecord = new GdnDtl();
            }
            gdnDtlRecord.setCostCenter(ifTransferDtl.getCostCenter());//设置成本中心

            gdnDtlRecord.setInvAttr(null);
            gdnDtlRecord.setGdnHeaderId(gdnHeader.getGdnHeaderId());
            gdnDtlRecord.setGdnLineNo(Integer.parseInt(ifTransferDtl.getBillLineNo()));
            gdnDtlRecord.setSourceShipNoticeItem(ifTransferDtl.getBillLineNo());
            Sku sku = skuMapper.selectOne(new QueryWrapper<>(new Sku().setSkuCode(ifTransferDtl.getMaterialCode())));
            if (sku == null) {
                throw new SyncException(syncType, billNo, "物料" + ifTransferDtl.getMaterialCode() + "不存在");
            }
            gdnDtlRecord.setSkuId(sku.getSkuId());
            gdnDtlRecord.setUnit(sku.getBaseUnit());
            gdnDtlRecord.setOrderQty(ifTransferDtl.getTransferQty());
            if (ifTransferDtl.getFromWhs() != null) {
                Warehouse warehouse = warehouseMapper.selectOneByWhsCode(ifTransferDtl.getFromWhs().trim());
                if (warehouse != null) {
                    gdnDtlRecord.setWhsId(warehouse.getWhsId());
                }
            }
            gdnDtlRecord.setSoNo(ifTransferDtl.getFromSoNo());
            gdnDtlRecord.setSoLineNo(ifTransferDtl.getFromSoLineNo());
            gdnDtlRecord.setComments(ifTransferDtl.getRemarks());
            gdnDtlRecord.setStatus(GdnDtlStatusEnum.CREATE.getCode());
//            gdnDtlRecord.setPoNo(ifTransferDtl.getAttribute1()); //订单号
            //2021.04.28订单号取值改为attribute5
            gdnDtlRecord.setPoNo(ifTransferDtl.getAttribute5());
            gdnDtlRecord.setQaStatus(QaStatusEnum.OK.code);
            gdnDtlRecord.setReserveNo(ifTransferDtl.getAttribute3()); //内部项目号

            if (isUpdate) {
                gdnDtlRecord.setModifyUser("system");
                gdnDtlRecord.setModifyTime(new Date());
                try {
                    gdnDtlMapper.updateById(gdnDtlRecord);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new SyncException(syncType, billNo, "调拨出库更新失败" + e.getMessage());
                }
            } else {
                gdnDtlRecord.setCreateUser("system");
                gdnDtlRecord.setCreateTime(new Date());
                gdnDtlRecord.setGdnLineNo(i);
                try {
                    gdnDtlMapper.insert(gdnDtlRecord);
                    i++;
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new SyncException(syncType, billNo, "调拨出库新增失败" + e.getMessage());
                }
            }
            //生成批次号
            Lotno lotno = lotnoService.getLotnoByGdnDtlId(gdnDtlRecord.getGdnDtlId());
            if (lotno != null) {
                gdnDtlRecord.setLotno(lotno.getLotno());
                int r = 1;
                try {
                    r = setLotAttr(gdnDtlRecord, lotno);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new SyncException(syncType, billNo, "设置批次属性" + r + "失败");
                }
            }
            gdnDtlMapper.updateLotNoAndAttr(gdnDtlRecord);
        }
        //更新状态为已同步
        int row = ifTransferHeaderMapper.updateFlagById(data.getIfTransferHeaderId());
        //检查是否有同步失败的记录，有则更新为成功
        JobSyncErrorData jobSyncErrorData = jobSyncErrorDataMapper.getSyncErrorDataByTypeAndCode(syncType, billNo);
        if (jobSyncErrorData != null && 0 == jobSyncErrorData.getIsSuccess()) {
            syncErrorDataService.updateSuccessByCode(syncType, billNo);
        }
    }

    /**
     * 设置批次属性1~12
     *
     * @param obj
     * @param lotno
     */
    private int setLotAttr(Object obj, Lotno lotno) throws Exception {
        int i = 1;
        for (i = 1; i < 13; i++) {
            try {
                Class<?> aClass = obj.getClass();
                Object value = lotno.getClass().getMethod("getLotAttr" + i).invoke(lotno, null);
                Method method = aClass.getMethod("setLotAttr" + i, String.class);
                method.invoke(obj, value);
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
        return i;
    }


    /**
     * 调拨入库 收货单
     *
     * @param data
     * @param isSyncError
     * @param syncType
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void syncIfTransferIn(IfTransferHeaderDto data, boolean isSyncError, String syncType) throws Exception {
        String billNo = data.getBillNo();
        String asnNo = "";
        List<IfTransferDtl> ifTransferDtlList = data.getIfTransferDtlList();
        if (CollectionUtil.isEmpty(ifTransferDtlList)) {
            throw new SyncException(syncType, billNo, "该调拨入库单下没有明细");
        }
        IfTransferDtl ifTransferDtl1 = ifTransferDtlList.get(0);
        Boolean isUpdate = true;

        //调拨入库 同步到 收货单 ASN
        AsnHeader asnHeader = asnHeaderMapper.selectOne(new QueryWrapper<>(new AsnHeader().setSourceNo(billNo)));
        if (asnHeader == null) {
            isUpdate = false;
            asnHeader = new AsnHeader();
        }
        BeanUtil.copyNonNull(data, asnHeader);
        asnHeader.setSourceNo(billNo);
        asnHeader.setAsnType(billTypeGloble);
        asnHeader.setErpMoveType(data.getMovedType());
        asnHeader.setAsnCreateTime(data.getCreateTime());
        asnHeader.setAsnCreateTime(data.getCreateTime());
        asnHeader.setAsnApprovedUser(data.getApprovedUser());
        asnHeader.setAsnApprovedTime(data.getApprovedTime());
        asnHeader.setComments(data.getRemarks());
        asnHeader.setReleaseStatus(0);
        asnHeader.setQcStatus(QcStatusEnum.未创建质检单.getCode());
        asnHeader.setStatus(AsnHeaderStatusEnum.CREATE.code);
        asnHeader.setFactory(ifTransferDtl1.getToOrg());
        DataItemDetailDTO dataItem = dataItemDetailApi.getDataItemDetailByPCodeAndName(DEFAULT_OWNER, DEFAULT_OWNER_NAME);
        asnHeader.setOwner(dataItem == null || dataItem.getItemValue() == null ? 0 : Integer.parseInt(dataItem.getItemValue()));

        if (isUpdate) {
            asnHeader.setModifyUser("system");
            asnHeader.setModifyTime(new Date());
            asnHeaderMapper.updateById(asnHeader);
        } else {
            try {
                asnNo = this.generateCode(data.getBillType());
            } catch (Exception e) {
                e.printStackTrace();
                throw new SyncException(syncType, billNo, "生成收货单号失败");
            }
            if (asnNo == null) {
                throw new SyncException(syncType, billNo, "生成收货单号失败");
            }
            asnHeader.setAsnNo(asnNo);
            asnHeader.setCreateTime(new Date());
            asnHeader.setCreateUser("system");
            try {
                asnHeaderMapper.insert(asnHeader);
            } catch (Exception e) {
                e.printStackTrace();
                log.info("调拨单->收货单主档同步新增失败");
                throw new SyncException(syncType, billNo, "调拨单->收货单主档同步新增失败");
            }
        }
        int i = 1;
        for (IfTransferDtl ifTransferDtl : ifTransferDtlList) {
            Boolean isUpdateDtl = true;
            AsnDtl asnDtl = asnDtlMapper.selectOne(new QueryWrapper<>(new AsnDtl().setSourceNo(
                    billNo).setSourceLineNo(ifTransferDtl.getBillLineNo())));
            if (asnDtl == null) {
                isUpdateDtl = true;
                asnDtl = new AsnDtl();
            }
            BeanUtil.copyNonNull(ifTransferDtl, asnDtl);
            asnDtl.setAsnHeaderId(asnHeader.getAsnHeaderId());
            asnDtl.setSourceNo(billNo);
            asnDtl.setSourceLineNo(ifTransferDtl.getBillLineNo());
            asnDtl.setAsnNo(asnHeader.getAsnNo());
            asnDtl.setAsnLineNo(ifTransferDtl.getBillLineNo());
            Warehouse warehouse = warehouseMapper.selectOneByWhsCode(ifTransferDtl.getToWhs().trim());
            if (warehouse != null) {
                if (asnHeader.getToWhs() == null) {
                    asnHeader.setToWhs(warehouse.getWhsId());
                    asnHeaderMapper.updateById(asnHeader);
                }
//                throw new SyncException(syncType, billNo, "仓库" + ifTransferDtl.getToWhs() + "不存在");
                asnDtl.setWhsId(warehouse.getWhsId());
            }
            asnDtl.setInvAttr(null);
            asnDtl.setSoNo(ifTransferDtl.getToSoNo());
            asnDtl.setSoLineNo(ifTransferDtl.getToSoLineNo());
            Sku sku = skuMapper.selectOne(new QueryWrapper<>(new Sku().setSkuCode(ifTransferDtl.getMaterialCode())));
            if (sku == null) {
                throw new SyncException(syncType, billNo, "物料" + ifTransferDtl.getMaterialCode() + "不存在");
            }
            asnDtl.setSkuId(sku.getSkuId());
            asnDtl.setSkuDesc(sku.getDescCn());
            asnDtl.setSkuDescEn(sku.getDescEn());
            asnDtl.setUnit(sku.getBaseUnit());
            asnDtl.setOrderQty(ifTransferDtl.getTransferQty());
            asnDtl.setOrderQtyEa(ifTransferDtl.getTransferQty());
            asnDtl.setRcvQty(BigDecimal.ZERO);
            asnDtl.setQcStatus(QcStatusEnum.未创建质检单.getCode());
            asnDtl.setQaStatus(QaStatusEnum.OK.getCode());
            asnDtl.setComments(ifTransferDtl.getRemarks());
            asnDtl.setStatus(AsnDtlStatusEnum.CREATE.code);
            asnDtl.setPoNo(ifTransferDtl.getAttribute1());
            asnDtl.setCostCenter(ifTransferDtl.getCostCenter());
            asnDtl.setReserveNo(ifTransferDtl.getAttribute3());
            if (isUpdate) {
                asnDtl.setModifyTime(new Date());
                asnDtl.setModifyUser("system");
                try {
                    asnDtlMapper.updateById(asnDtl);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new SyncException(syncType, billNo, "调拨入库明细更新失败" + e.getMessage());
                }
            } else {
                asnDtl.setCreateTime(new Date());
                asnDtl.setCreateUser("system");
                asnDtl.setAsnLineNo(String.valueOf(i));
                try {
                    asnDtlMapper.insert(asnDtl);
                    i++;
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new SyncException(syncType, billNo, "调拨入库明细新增失败" + e.getMessage());
                }
                //新增要生成批次号
                Lotno lotno = lotnoService.getLotnoByAsnDtlId(asnDtl.getAsnDtlId());
                if (lotno != null) {
                    asnDtl.setLotno(lotno.getLotno());
                    int r = 1;
                    try {
                        r = setLotAttr(asnDtl, lotno);
                    } catch (Exception e) {
                        e.printStackTrace();
                        throw new SyncException(syncType, billNo, "设置批次属性" + r + "失败");
                    }
                    asnDtlMapper.updateLotNoAndAttr(asnDtl);
                }
            }
            //更新状态为已同步
            int row = ifTransferHeaderMapper.updateFlagById(data.getIfTransferHeaderId());
            //检查是否有同步失败的记录，有则更新为成功
            JobSyncErrorData jobSyncErrorData = jobSyncErrorDataMapper.getSyncErrorDataByTypeAndCode(syncType, billNo);
            if (jobSyncErrorData != null && 0 == jobSyncErrorData.getIsSuccess()) {
                syncErrorDataService.updateSuccessByCode(syncType, billNo);
            }
        }
    }


    /**
     * 调拨单
     *
     * @param data
     * @param isSyncError
     * @param syncType
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void syncIfTransfer(IfTransferHeaderDto data, boolean isSyncError, String syncType) throws Exception {
        String billNo = data.getBillNo();
        Boolean isUpdate = true;
        String toWhsCode = "";
        String fmWhsCode = "";
        String transferNo = "";
        if ("7".equals(data.getBillType())) {
            return;
        }
        List<IfTransferDtl> ifTransferDtlList = data.getIfTransferDtlList();
        if (CollectionUtil.isEmpty(ifTransferDtlList)) {
            throw new SyncException(syncType, billNo, "该调拨单下没有明细");
        }
        IfTransferDtl ifTransferDtl1 = ifTransferDtlList.get(0);


        //调拨业务 同步到 调拨单 transfer

        TransferHeader transferHeader = transferHeaderMapper.selectOne(new QueryWrapper<>(new TransferHeader().setSourceNo(billNo)));
        if (transferHeader == null) {
            isUpdate = false;
            transferHeader = new TransferHeader();
        }
        BeanUtil.copyNonNull(data, transferHeader);
        transferHeader.setSourceNo(billNo);
        transferHeader.setPurchsingOrg(data.getPurchasingOrg());
        transferHeader.setCompanyCode(data.getCompanyCode());
        transferHeader.setTransferType(billTypeGloble);
        transferHeader.setErpMoveType(data.getMovedType());
        transferHeader.setTransferDept(data.getDept());
        transferHeader.setTransferCreateUser(data.getCreateUser());
        transferHeader.setTransferCreateTime(data.getCreateTime());
        transferHeader.setTransferApprovedUser(data.getApprovedUser());
        transferHeader.setTransferApprovedTime(data.getApprovedTime());
        transferHeader.setComments(data.getRemarks());
        transferHeader.setStatus(TransferHeaderStatusEnum.CREATE.code);
        toWhsCode = ifTransferDtl1.getToWhs();
        fmWhsCode = ifTransferDtl1.getFromWhs();
        String fromOrg = ifTransferDtl1.getFromOrg();
        String toOrg = ifTransferDtl1.getToOrg();

        Warehouse warehouseTo = warehouseMapper.selectOneByWhsCode(toWhsCode);
        Warehouse warehouseFm = warehouseMapper.selectOneByWhsCode(fmWhsCode);

        //仓库查不到写个0
        if (warehouseTo != null) {
            transferHeader.setToWhs(warehouseTo.getWhsId());
        } else {
            transferHeader.setToWhs(0);
        }
        if (warehouseFm != null) {
            transferHeader.setFmWhs(warehouseFm.getWhsId());
        } else {
            transferHeader.setFmWhs(0);
        }

        //改为先查询映射表，后面再查询仓库---start
//        CodeMapping codeMapping_fm = codeMappingService.selectByWhsCodeAndFactory(fmWhsCode, fromOrg);
//        if (codeMapping_fm==null) {
//            transferHeader.setToWhs(0);
//        }else {
//            Warehouse warehouseFm = warehouseMapper.selectOneByWhsCode(codeMapping_fm.getWmsCode());
//            if (warehouseFm==null) {
//                transferHeader.setToWhs(-1);
//            }else {
//                transferHeader.setToWhs(warehouseFm.getWhsId());
//            }
//        }
//
//        CodeMapping codeMapping_to = codeMappingService.selectByWhsCodeAndFactory(toWhsCode, toOrg);
//        if (codeMapping_to==null) {
//            transferHeader.setFmWhs(0);
//        }else {
//            Warehouse warehouseTo = warehouseMapper.selectOneByWhsCode(codeMapping_to.getWmsCode());
//            if (warehouseTo==null) {
//                transferHeader.setToWhs(-1);
//            }else {
//                transferHeader.setToWhs(warehouseTo.getWhsId());
//            }
//        }
        //改为先查询映射表，后面再查询仓库---end


        //如果类型是1,2借机,还机;
        DataItemDetailDTO defaultWhs = null;
        try {
            defaultWhs = dataItemDetailApi.getDataItemDetailByPCodeAndName(DATA_CODE, DATA_NAME);
        } catch (Exception e) {
            e.printStackTrace();
            log.warn("数据字典取仓库失败");
            throw new SyncException(syncType, billNo, "数据字典取仓库失败" + e.getMessage());
        }
        if (defaultWhs != null) {
            String itemValue = defaultWhs.getItemValue().trim();
            Warehouse warehouse = warehouseMapper.selectOneByWhsCode(itemValue);
            if (warehouse != null) {
                //借机,设置默认toWhs
                if (data.getBillType().equals("1")) {
                    transferHeader.setToWhs(warehouse.getWhsId());
                }
                //还机,设置默认fmWhs
                if (data.getBillType().equals("2")) {
                    transferHeader.setFmWhs(warehouse.getWhsId());
                }
            }
        }
        if (data.getBillType().equals("8")) {
            //如果同步类型是8，销售订单调拨,仓库需要通过CodeMappingService转一下
            CodeMapping codeMappingTo = codeMappingNewService.selectByMappingCodeAndFacCode(ifTransferDtl1.getToWhs(), ifTransferDtl1.getToOrg());
            CodeMapping codeMappingFm = codeMappingNewService.selectByMappingCodeAndFacCode(ifTransferDtl1.getFromWhs(), ifTransferDtl1.getToOrg());
            if (codeMappingTo != null) {
                toWhsCode = codeMappingTo.getWmsCode().trim();
                Warehouse warehouse = warehouseMapper.selectOneByWhsCode(toWhsCode);
                if (warehouse != null) {
                    transferHeader.setToWhs(warehouse.getWhsId());
                } else {
                    transferHeader.setToWhs(-1);
                }
            } else {
                transferHeader.setToWhs(0);
            }
            if (codeMappingFm != null) {
                fmWhsCode = codeMappingFm.getWmsCode().trim();
                Warehouse warehouse = warehouseMapper.selectOneByWhsCode(fmWhsCode);
                if (warehouse != null) {
                    transferHeader.setFmWhs(warehouse.getWhsId());
                } else {
                    transferHeader.setFmWhs(-1);
                }
            } else {
                transferHeader.setFmWhs(0);
            }
        }
        if (isUpdate) {
            transferHeader.setModifyUser("system");
            transferHeader.setModifyTime(new Date());
            try {
                transferHeaderMapper.updateById(transferHeader);
            } catch (Exception e) {
                e.printStackTrace();
                log.warn("调拨单{},同步更新失败,类型{}", billNo, data.getBillNo());
                log.error("调拨单同步更新失败：" + e.getMessage());
                throw new SyncException(syncType, billNo, "调拨单同步更新失败" + e.getMessage());
            }
        } else {
            transferHeader.setCreateTime(new Date());
            transferHeader.setCreateUser("system");
            try {
                //生成单号
                transferNo = this.generateCode(data.getBillType());
            } catch (Exception e) {
                e.printStackTrace();
                log.warn("调拨单{},生成调拨单号失败");
                throw new SyncException(syncType, billNo, "生成调拨单号失败");
            }
            transferHeader.setTransferNo(transferNo);
            try {
                transferHeaderMapper.insert(transferHeader);
            } catch (Exception e) {
//                e.printStackTrace();
                log.warn("调拨单{},同步新增失败,类型{}", billNo, data.getBillNo());
                log.error("调拨单同步新增失败：" + e.getMessage());
                throw new SyncException(syncType, billNo, "调拨单同步新增失败" + e.getMessage());
            }
        }
        int i = 1;
        for (IfTransferDtl ifTransferDtl : ifTransferDtlList) {
            Boolean isUpdateDtl = true;
            TransferDtl transferDtl = transferDtlMapper.selectOne(new QueryWrapper<>(
                    new TransferDtl().setSourceNo(billNo).setSourceLineNo(ifTransferDtl.getBillLineNo())));
            if (transferDtl == null) {
                isUpdateDtl = false;
                transferDtl = new TransferDtl();
            }
            BeanUtil.copyNonNull(ifTransferDtl, transferDtl);
            transferDtl.setTransferNo(transferHeader.getTransferNo());
            transferDtl.setTransferHeaderId(transferHeader.getTransferHeaderId());
            transferDtl.setSourceNo(billNo);
            DataItemDetailDTO dataItem = dataItemDetailApi.getDataItemDetailByPCodeAndName(DEFAULT_OWNER, DEFAULT_OWNER_NAME);
            transferDtl.setToOwner(dataItem == null || dataItem.getItemValue() == null ? 0 : Integer.parseInt(dataItem.getItemValue()));
            transferDtl.setFmOwner(dataItem == null || dataItem.getItemValue() == null ? 0 : Integer.parseInt(dataItem.getItemValue()));
            transferDtl.setSourceLineNo(ifTransferDtl.getBillLineNo());
            transferDtl.setFmFactory(ifTransferDtl.getFromOrg());
            transferDtl.setToFactory(ifTransferDtl.getToOrg());
            transferDtl.setFmInvAttr(null);
            transferDtl.setToInvAttr(null);
//            transferDtl.setFmVendor(ifTransferDtl.getAttribute6());
//            transferDtl.setToVendor(ifTransferDtl.getAttribute6());
            transferDtl.setUdf5(ifTransferDtl.getAttribute6()); //供应商
            transferDtl.setFmSoNo(ifTransferDtl.getFromSoNo());
            transferDtl.setFmSoLineNo(ifTransferDtl.getFromSoLineNo());
            transferDtl.setToSoNo(ifTransferDtl.getToSoNo());
            transferDtl.setToSoLineNo(ifTransferDtl.getToSoLineNo());
            Sku sku = skuMapper.selectOne(new QueryWrapper<>(new Sku().setSkuCode(ifTransferDtl.getMaterialCode())));
            if (sku == null) {
                throw new SyncException(syncType, billNo, "物料" + ifTransferDtl.getMaterialCode() + "不存在");
            }
            transferDtl.setUnit(sku.getBaseUnit());
            transferDtl.setFmSku(sku.getSkuId());
            transferDtl.setToSku(sku.getSkuId());
            transferDtl.setOrderQty(ifTransferDtl.getTransferQty().intValue());
            transferDtl.setTransferTime(ifTransferDtl.getTransferTime());
            transferDtl.setReturnTime(ifTransferDtl.getReturnTime());
            transferDtl.setComments(ifTransferDtl.getRemarks());
            transferDtl.setToPo(ifTransferDtl.getAttribute1());
            transferDtl.setFmPo(ifTransferDtl.getAttribute5());
            transferDtl.setStatus(TransferDtlStatusEnum.CREATE.code);
            transferDtl.setToQaStatus(1);
            transferDtl.setFmQaStatus(1);
            transferDtl.setTransitQty(BigDecimal.ZERO.intValue());
            transferDtl.setCmpQty(BigDecimal.ZERO.intValue());
            if (isUpdateDtl) {
                transferDtl.setModifyTime(new Date());
                transferDtl.setModifyUser("system");
                try {
                    transferDtlMapper.updateById(transferDtl);
                } catch (Exception e) {
                    log.warn("调拨单{}明细同步更新失败,类型{}", billNo, data.getBillType());
                    log.error("调拨单明细同步更新失败" + e.getMessage());
                    throw new SyncException(syncType, billNo, "调拨单明细同步更新失败" + e.getMessage());
                }
            } else {
                transferDtl.setCreateTime(new Date());
                transferDtl.setCreateUser("system");
                transferDtl.setTransferLineNo(String.valueOf(i));
                try {
                    transferDtlMapper.insert(transferDtl);
                    i++;
                } catch (Exception e) {
                    log.error("调拨单明细同步新增失败" + e.getMessage());
                    log.warn("调拨单{}明细同步新增失败,类型{}", billNo, data.getBillType());
                    throw new SyncException(syncType, billNo, "调拨单明细同步新增失败" + e.getMessage());
                }
            }
            //生成批次号
            Lotno lotnoSource = lotnoService.getLotnoByTransferDtlId(transferDtl.getTransferDtlId(), 0);
            Lotno lotnoTo = lotnoService.getLotnoByTransferDtlId(transferDtl.getTransferDtlId(), 1);
            if (lotnoSource == null) {
                log.info("调拨单{}来源批次号为空", billNo);
            } else {
                log.info("调拨单：来源批次号：{},单号:{}", lotnoSource.getLotno(), billNo);
            }
            if (lotnoTo == null) {
                log.info("调拨单{}去向批次号为空", billNo);
            } else {
                log.info("调拨单：去向批次号：{},单号:{}", lotnoTo.getLotno(), billNo);
            }
            if (lotnoSource != null) {
                transferDtl.setFmLotno(lotnoSource.getLotno());
                int r = 1;
                try {
                    r = setLotAttrFm(transferDtl, lotnoSource);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new SyncException(syncType, billNo, "设置来源批次属性" + r + "失败");
                }
//                    transferDtlMapper.updateLotNoAndAttr(transferDtl);
            }
            if (lotnoTo != null) {
                transferDtl.setToLotno(lotnoTo.getLotno());
                int r = 1;
                try {
                    r = setLotAttrTo(transferDtl, lotnoSource);
                } catch (Exception e) {
                    e.printStackTrace();
                    throw new SyncException(syncType, billNo, "设置去向批次属性" + r + "失败");
                }
            }
            transferDtlMapper.updateLotNoAndAttr(transferDtl);
        }
        //更新状态为已同步
        int row = ifTransferHeaderMapper.updateFlagById(data.getIfTransferHeaderId());
        //检查是否有同步失败的记录，有则更新为成功
        JobSyncErrorData jobSyncErrorData = jobSyncErrorDataMapper.getSyncErrorDataByTypeAndCode(syncType, billNo);
        if (jobSyncErrorData != null && 0 == jobSyncErrorData.getIsSuccess()) {
            syncErrorDataService.updateSuccessByCode(syncType, billNo);
        }
    }


    /**
     * 设置批次属性1~12(调拨单来源)
     *
     * @param obj
     * @param lotno
     */
    private int setLotAttrFm(Object obj, Lotno lotno) throws Exception {
        int i = 1;
        for (i = 1; i < 13; i++) {
            try {
                Class<?> aClass = obj.getClass();
                Object value = lotno.getClass().getMethod("getLotAttr" + i).invoke(lotno, null);
                Method method = aClass.getMethod("setFmLotAttr" + i, String.class);
                method.invoke(obj, value);
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
        return i;
    }

    /**
     * 设置批次属性1~12(调拨单去向)
     *
     * @param obj
     * @param lotno
     */
    private int setLotAttrTo(Object obj, Lotno lotno) throws Exception {
        int i = 1;
        for (i = 1; i < 13; i++) {
            try {
                Class<?> aClass = obj.getClass();
                Object value = lotno.getClass().getMethod("getLotAttr" + i).invoke(lotno, null);
                Method method = aClass.getMethod("setToLotAttr" + i, String.class);
                method.invoke(obj, value);
            } catch (Exception e) {
                e.printStackTrace();
                break;
            }
        }
        return i;
    }


    /**
     * 根据billType判断编码生成规则并生成
     *
     * @param billType
     * @return
     */
    public String generateCode(String billType) {
        changeType(billType);
        return basicSimpleCodeRuleApi.GenerateCode(billCodeRule);
    }

    /**
     * 单据类型转换
     *
     * @param billType
     */
    private void changeType(String billType) {
        switch (billType) {
            case "1":
                billCodeRule = T05;
                billTypeGloble = "T05";
                break;
            case "2":
                billCodeRule = T06;
                billTypeGloble = "T06";
                break;
            case "3":
                billCodeRule = D99;
                billTypeGloble = "D99";
                break;
            case "4":
                billCodeRule = R99;
                billTypeGloble = "R99";
                break;
            case "5":
                billCodeRule = R08;
                billTypeGloble = "R08";
                break;
            case "6":
                billCodeRule = D08;
                billTypeGloble = "D08";
                break;
            case "7":
                billCodeRule = T03;
                billTypeGloble = "T03";
                break;
            case "8":
                billCodeRule = T04;
                billTypeGloble = "T04";
                break;
        }
    }
}
